#include "main.h"

#include <QApplication>

MainWindow::MainWindow()
{
	ver = "1.1";
    setupInterface();
}

void MainWindow::setupInterface() {
	main_dial = new QDialog();
	main_dial->setWindowTitle("QRename");
	main_dial->setWindowIcon(QIcon(QString::fromUtf8(":/icons/images/rename.png")));
	QGridLayout * main_glayout = new QGridLayout(main_dial);
	QGridLayout * glayout = new QGridLayout();
	QLabel * path_lbl = new QLabel (main_dial);
	path_lbl->setText(tr("Folder path"));
	glayout->addWidget(path_lbl, 0, 0);
	path_le = new QLineEdit(main_dial);
	glayout->addWidget(path_le, 0, 1);
	QPushButton * browse_btn = new QPushButton(main_dial);
	browse_btn->setText(tr("Browse"));
	QObject::connect(browse_btn, SIGNAL(released()), this, SLOT(browse()));
	glayout->addWidget(browse_btn, 0, 2);
	QLabel * name_lbl = new QLabel (main_dial);
	name_lbl->setText(tr("Set new name"));
	glayout->addWidget(name_lbl, 1, 0);
	name_le = new QLineEdit(main_dial);
	glayout->addWidget(name_le, 1, 1);
	add_var = new QPushButton(main_dial);
	add_var->setText(tr("Add variable"));
	//QObject::connect(add_var, SIGNAL(released()), this, SLOT(addVariable()));
	setVarMenu();
	glayout->addWidget(add_var, 1, 2);
	QLabel * exceptions_lbl = new QLabel (main_dial);
	exceptions_lbl->setText(tr("Exceptions"));
	glayout->addWidget(exceptions_lbl, 2, 0);
	except_le = new QLineEdit(main_dial);
    QObject::connect(except_le, SIGNAL(editingFinished()), this, SLOT(reloadContents()));
	glayout->addWidget(except_le, 2, 1);
	QPushButton * add_except_btn = new QPushButton (main_dial);
	add_except_btn->setText(tr("Add exception"));
	QObject::connect(add_except_btn, SIGNAL(released()), this, SLOT(addException()));
	glayout->addWidget(add_except_btn, 2, 2);
	main_glayout->addLayout(glayout, 0, 0);
	cont_list = new QTreeWidget (main_dial);
	cont_list->setHeaderLabel(tr("Contents"));
	cont_list->setColumnCount(1);
	QObject::connect(path_le, SIGNAL(editingFinished()), this, SLOT(reloadContents()));
	main_glayout->addWidget(cont_list, 1, 0);
	QGroupBox * options_gb = new QGroupBox (tr("Options"), main_dial);
	QGridLayout * gb_layout = new QGridLayout (options_gb);
	dirs_chck = new QCheckBox (main_dial);
	dirs_chck->setText(tr("Rename directories"));
	gb_layout->addWidget(dirs_chck, 0, 0);
	subdirs_chck = new QCheckBox (main_dial);
	subdirs_chck->setText(tr("Rename files in subdirectories"));
    subdirs_chck->setChecked(false);
	//QObject::connect(dirs_chck, SIGNAL(toggled(bool)), subdirs_chck, SLOT(setEnabled(bool)));
	QObject::connect(dirs_chck, SIGNAL(clicked()), this, SLOT(reloadContents()));
	QObject::connect(subdirs_chck, SIGNAL(clicked()), this, SLOT(reloadContents()));
	gb_layout->addWidget(subdirs_chck, 0, 1);
	main_glayout->addWidget(options_gb, 2, 0);
	QHBoxLayout * bottom_hlayout = new QHBoxLayout;
	QPushButton * about_btn = new QPushButton (main_dial);
	about_btn->setText(tr("About"));
	QObject::connect(about_btn, SIGNAL(released()), this, SLOT(aboutDialogue()));
	bottom_hlayout->addWidget(about_btn);
	bottom_hlayout->addStretch();
	QPushButton * start_btn = new QPushButton (main_dial);
	start_btn->setText(tr("Start"));
	QObject::connect(start_btn, SIGNAL(released()), this, SLOT(start()));
	bottom_hlayout->addWidget(start_btn);
	main_glayout->addLayout(bottom_hlayout, 3, 0);
	main_dial->show();
}

void MainWindow::browse()
{
	QString inputDirectory = QFileDialog::getExistingDirectory(
                    this,
                    "Choose a directory",
                    QDir::homePath(),
                    QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
    path_le->setText(inputDirectory);
    reloadContents();
}

void MainWindow::start()
{
	if (path_le->text() == "") return;
	if (name_le->text() == "") return;
	renamed_count = 0;
    failed_files.clear();
    
	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
	subRename(path_le->text(), name_le->text(), cont_list->topLevelItem(0));
	reloadContents();
    QApplication::restoreOverrideCursor();
	
    if (failed_files.count() != 0) {
        errorDialogue();
    }
	QMessageBox::information(this, "QRename", tr("%1 file(s) renamed").arg(renamed_count));
}

void MainWindow::subRename(QString dir_path, QString new_name, QTreeWidgetItem * parent_item)
{
	QDir directory (dir_path);
	
	for (int i = 0; i < parent_item->childCount(); ++i) {
        QString file_name = new_name;
		QFileInfo file_info (parent_item->child(i)->data(0, Qt::UserRole).toString());
		if (file_info.isDir() && !file_info.isSymLink()) {
			if (subdirs_chck->isChecked()) {
				subRename(file_info.absoluteFilePath(), new_name, parent_item->child(i));
			}
		}
        if (parent_item->child(i)->checkState(0) == Qt::Unchecked) continue;
		file_name.replace("%n", file_info.fileName());
		if (file_info.isDir() && !file_info.isSymLink()) {
			file_name.remove("%s");
			/*if (subdirs_chck->isChecked()) {
				subRename(file_info.absoluteFilePath(), new_name, parent_item->child(i));
			}*/
		} else {
			file_name.replace("%s", QString(".%1").arg(file_info.suffix()));
		}
		file_name.replace("%b", file_info.baseName());
		file_name.replace("%i", QString("%1").arg(i+1));
		QFile file (file_info.absoluteFilePath());
		if (!file.rename(QString("%1/%2").arg(dir_path).arg(file_name))) {
			//QMessageBox::information(this, tr("QRename"), tr("Failed to rename file %1").arg(file_info.absoluteFilePath()));
            failed_files << file_info.absoluteFilePath();
		} else { renamed_count++; }
	}
}

void MainWindow::setVarMenu()
{
	QMenu * menu = new QMenu (add_var);
	add_var->setMenu(menu);
	QAction * current_name_act = new QAction(menu);
	current_name_act->setText(tr("Current name"));
	connect(current_name_act, SIGNAL(triggered()), this, SLOT(addCurName()));
	menu->addAction(current_name_act);
	QAction * index_act = new QAction(menu);
	index_act->setText(tr("Index"));
	connect(index_act, SIGNAL(triggered()), this, SLOT(addIndex()));
	menu->addAction(index_act);
	QAction * prefix_act = new QAction(menu);
	prefix_act->setText(tr("Base name"));
	connect(prefix_act, SIGNAL(triggered()), this, SLOT(addPrefix()));
	menu->addAction(prefix_act);
	QAction * suffix_act = new QAction(menu);
	suffix_act->setText(tr("Suffix"));
	connect(suffix_act, SIGNAL(triggered()), this, SLOT(addSuffix()));
	menu->addAction(suffix_act);
}

void MainWindow::addCurName()
{
	name_le->setText(QString("%1%2").arg(name_le->text()).arg("%n"));
}

void MainWindow::addIndex()
{
	name_le->setText(QString("%1%2").arg(name_le->text()).arg("%i"));
}

void MainWindow::addPrefix()
{
	name_le->setText(QString("%1%2").arg(name_le->text()).arg("%b"));
}

void MainWindow::addSuffix()
{
	name_le->setText(QString("%1%2").arg(name_le->text()).arg("%s"));
}

void MainWindow::reloadContents()
{
	cont_list->clear();
	cont_list->setColumnCount(1);
	cont_list->setHeaderLabel(tr("Contents"));
	if (path_le->text()=="") return;
    exceptions.clear();
	QStringList exceptions0 = except_le->text().split(", ");
    for (int i = 0; i < exceptions0.count(); ++i) {
        exceptions << exceptions0.at(i).split(",");
    }
	
	QTreeWidgetItem * root_item = new QTreeWidgetItem(cont_list);
	root_item->setText(0, tr("Root"));
	root_item->setCheckState(0, Qt::Checked);
	root_item->setExpanded(true);
	subReloadContents(path_le->text(), root_item);
	
}

void MainWindow::subReloadContents(QString path, QTreeWidgetItem * parent_item)
{
	QDir directory (path);
	QFileInfoList entries = directory.entryInfoList((QDir::NoDotAndDotDot | QDir::AllEntries), (QDir::Name | QDir::DirsFirst | QDir::IgnoreCase));
	
	for (int i = 0; i < entries.count(); ++i) {
		QTreeWidgetItem * item = new QTreeWidgetItem (parent_item);
		item->setText(0, entries.at(i).fileName());
		item->setCheckState(0, Qt::Checked);
		item->setData(0, Qt::UserRole, entries.at(i).absoluteFilePath());
        for (int e = 0; e < exceptions.count(); ++e) {
            if (QRegExp(exceptions.at(e), Qt::CaseInsensitive, QRegExp::Wildcard).exactMatch(entries.at(i).fileName())) {
                item->setCheckState(0, Qt::Unchecked);
            }
        }
		if (entries.at(i).isDir() && !entries.at(i).isSymLink()) {
			if (!dirs_chck->isChecked()) {
				item->setCheckState(0, Qt::Unchecked);
			}
			item->setIcon(0, QIcon(QString::fromUtf8(":/icons/images/folder.png")));
			if (subdirs_chck->isChecked()) {
				subReloadContents(entries.at(i).absoluteFilePath(), item);
			}
		} else {
            item->setIcon(0, QIcon(QString::fromUtf8(":/icons/images/file.png")));
        }
	}
}

void MainWindow::addException()
{
    if (except_le->text() == "") {
        except_le->setText("*.*");
    } else {
        except_le->setText(QString("%1, *.*").arg(except_le->text()));
    }
}

void MainWindow::aboutDialogue()
{
    about_dial = new QDialog();
    about_dial->setWindowTitle(tr("About QRename"));
	about_dial->setWindowIcon(QIcon(QString::fromUtf8(":/icons/images/rename.png")));
	QHBoxLayout * top_hlayout = new QHBoxLayout;
    QGridLayout * about_glayout = new QGridLayout(about_dial);
	QLabel * label = new QLabel (about_dial);
	label->setPixmap(QPixmap(QString::fromUtf8(":/icons/images/rename128.png")));
	top_hlayout->addWidget(label);
	/*QLabel * qrename_label = new QLabel (about_dial);
	qrename_label->setText("<span style=\"font-size:12pt;\">QRename</span>");
	top_hlayout->addWidget(qrename_label);
	top_hlayout->addStretch();*/
	about_glayout->addLayout(top_hlayout, 0, 0);
    QTabWidget * about_tbw = new QTabWidget (about_dial);
    QTextBrowser * qrename_tbw = new QTextBrowser ();
    //--------------------------------------------------------------------------
    QString about = "<p style=\"font-family: sans-serif; font-style:italic;\"><span style=\"font-size:12pt;\">QRename</span><br>";
	about.append("<span style=\"font-size:8pt;\">");
    about.append(tr("Version"));
    about.append(QString(" %1</span></p><p></p>").arg(ver));
    about.append("http://code.google.com/p/qrename/");
	about.append("<p style=\"font-family: sans-serif; font-size:8pt;\">");
    about.append(tr("QRename is a simple Qt application for renaming many files and folders at once."));
    about.append("</p><p></p>");
	about.append("<p style=\"font-family: sans-serif; font-size:8pt;\">");
    about.append(tr("This programme is distributed under the terms of the GPL v2."));
	about.append("</p><p></p>");
	about.append(QString::fromUtf8("<p style=\"font-family: sans-serif; font-size:8pt;\">2008 <span style=\"font-style:italic;\">Mat\303\272\305\241 Tomlein</span> (matus.tomlein@gmail.com), <span style=\"font-style:italic;\">Robert Borgu\304\276a</span></p>"));
	about.append("<p></p><p style=\"font-family: sans-serif; font-size:8pt;\">");
	about.append(tr("The programme is provided AS IS with ABSOLUTELY NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE."));
	about.append("</p>");
#ifdef Q_WS_MAC
	about.remove("font-family: sans-serif;");
	about.replace("font-size:12pt;", "font-size:14pt;");
	about.replace("font-size:8pt;", "font-size:10pt;");
#endif
    qrename_tbw->setHtml(about);
    about_tbw->addTab(qrename_tbw, tr("About QRename"));
    //--------------------------------------------------------------------------
    QTextBrowser * qt_tbw = new QTextBrowser ();
    QString aboutQt = "<p style=\"font-family: sans-serif; font-style:italic;\"><span style=\"font-size:12pt;\">";
    aboutQt.append(tr("About Qt"));
	aboutQt.append("</span></p><p></p><p style=\"font-family: sans-serif; font-size:8pt; font-style:italic;\">");
	aboutQt.append(tr("This programme uses Qt Open Source Edition version %1.").arg(qVersion()));
	aboutQt.append("</p><p></p><p style=\"font-family: sans-serif; font-size:8pt;\">");
	aboutQt.append(tr("Qt is a C++ toolkit for cross-platform application development."));
	aboutQt.append("</p><p></p><p style=\"font-family: sans-serif; font-size:8pt;\">");
	aboutQt.append(tr("Qt provides single-source portability across MS Windows, Mac OS X, Linux and all major commercial Unix variants. Qt is also available for embedded devices as Qtopia Core."));
	aboutQt.append("</p><p></p><p style=\"font-family: sans-serif; font-size:8pt;\">");
	aboutQt.append(tr("Qt is a Trolltech product. See <span style=\"font-style:italic;\">http://www.trolltech.com/qt/</span> for more information."));
	aboutQt.append("</p>");
#ifdef Q_WS_MAC
	aboutQt.remove("font-family: sans-serif;");
	aboutQt.replace("font-size:12pt;", "font-size:14pt;");
	aboutQt.replace("font-size:8pt;", "font-size:10pt;");
#endif
    qt_tbw->setHtml(aboutQt);
    about_tbw->addTab(qt_tbw, tr("About Qt"));
    about_glayout->addWidget(about_tbw, 1, 0);
    QHBoxLayout * hlayout = new QHBoxLayout;
    hlayout->addStretch();
    QPushButton * about_quit_btn = new QPushButton (about_dial);
    about_quit_btn->setText(tr("Close"));
    QObject::connect(about_quit_btn, SIGNAL(released()), about_dial, SLOT(close()));
    hlayout->addWidget(about_quit_btn);
    about_glayout->addLayout(hlayout, 2, 0);
    about_dial->show();
}

void MainWindow::errorDialogue()
{
    QDialog * error_dial = new QDialog();
    error_dial->setWindowTitle(tr("Failed to rename files"));
    error_dial->setWindowIcon(QIcon(QString::fromUtf8(":/icons/images/rename.png")));
    QGridLayout * error_glayout = new QGridLayout(error_dial);
    QLabel * label1 = new QLabel (error_dial);
    label1->setText(tr("Failed to rename files:"));
    error_glayout->addWidget(label1, 0, 0);
    QTextBrowser * error_tbw = new QTextBrowser (error_dial);
    QString errors_str;
    for (int i = 0; i < failed_files.count(); ++i) {
        errors_str.append(QString("%1<br>").arg(failed_files.at(i)));
    }
    error_tbw->setHtml(errors_str);
    error_glayout->addWidget(error_tbw, 1, 0);
    QHBoxLayout * hlayout = new QHBoxLayout;
    hlayout->addStretch();
    QPushButton * error_quit_btn = new QPushButton (error_dial);
    error_quit_btn->setText(tr("Close"));
    QObject::connect(error_quit_btn, SIGNAL(released()), error_dial, SLOT(close()));
    hlayout->addWidget(error_quit_btn);
    error_glayout->addLayout(hlayout, 2, 0);
    error_dial->show();
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow * window = new MainWindow;
    return app.exec();
}
